using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using ProjectEuler.Core.Helpers;

namespace ProjectEuler.Core
{
    public class Problem47 : IProjectEulerProblem
    {
        protected IList<long> FindFirstNConsecutiveIntsToHaveNDistinctPrimesFactors(long n)
        {
            long i = 13;
            var consecutiveList = new List<long>();
            while (true)
            {
                var primeFactors = MathHelper.PrimeFactorsOf(i);
                if (primeFactors.Distinct().Count() != n)
                {
                    consecutiveList.Clear();
                }
                else
                {
                    consecutiveList.Add(i);
                }
                if (consecutiveList.Count == n)
                {
                    return consecutiveList;
                }
                i++;
            }
        }

        public int Number
        {
            get { return 47; }
        }

        public string Description
        {
            get { return "Find the first four consecutive integers to have four distinct primes factors. What is the first of these numbers?"; }
        }

        public string Answer
        {
            get { return FindFirstNConsecutiveIntsToHaveNDistinctPrimesFactors(4).First().ToString(); }
        }
    }

    [TestFixture]
    public class Problem47Tests : Problem47
    {
        [Test]
        public void First_two_consecutive_numbers_with_two_prime_factors()
        {
            var list = FindFirstNConsecutiveIntsToHaveNDistinctPrimesFactors(2);
            Assert.IsTrue(list.Count == 2);
            Assert.IsTrue(list.Contains(14));
            Assert.IsTrue(list.Contains(15));
        }
        
        [Test]
        public void First_three_consecutive_numbers_with_three_prime_factors()
        {
            var list = FindFirstNConsecutiveIntsToHaveNDistinctPrimesFactors(3);
            Assert.IsTrue(list.Count == 3);
            Assert.IsTrue(list.Contains(644));
            Assert.IsTrue(list.Contains(645));
            Assert.IsTrue(list.Contains(646));
        }
    }
}